package com.bjsxt.util;

import org.apache.commons.lang3.StringUtils;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;
import org.supercsv.util.CsvContext;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 导出 CSV 文件工具类
 *
 * @author ALIENWARE
 * @version v1.0.0
 * @create 4/27/2024
 */
public class ReportCsvUtils {
    /**
     * 将 Long 类型的数值转换为 String 类型
     */
    public static final CellProcessor LONG_TO_STRING_PROCESSORS = new CellProcessor() {
        @Override
        public <T> T execute(Object o, CsvContext csvContext) {
            return (T) String.valueOf(o);
        }
    };
    /**
     * Decimal 对象的数值转换对象，转为8位有有效数字
     */
    private final static DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00000000");
    /**
     * 将 BigDecimal 数字转换为 8 位有效数字
     */
    public static final CellProcessor BIG_DECIMAL_TO_STRING8 = new CellProcessor() {
        @Override
        public <T> T execute(Object o, CsvContext csvContext) {
            return (T) DECIMAL_FORMAT.format(o);
        }
    };
    /**
     * Date 转换字符串对象 Date -> yyyy-MM-dd HH:mm:ss
     */
    private final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 将 Date 对象转换为 yyyy-MM-dd HH:mm:ss 的形式
     */
    public static final CellProcessor DATE_TO_STRING_PROCESSORS = new CellProcessor() {
        @Override
        public <T> T execute(Object o, CsvContext csvContext) {
            return o == null ? (T) o : (T) SIMPLE_DATE_FORMAT.format((Date) o);
        }
    };

    /**
     * 向 response 对象写入一个集合
     *
     * @param response   相应对象
     * @param header     需要转换的信息的中文列名集合
     * @param properties 需要转换信息的字段列名集合
     * @param fileName   需要转换为的文件名称
     * @param sourceList csv 转换文件的源数据
     * @throws Exception 转换过程 中发生了异常
     */
    public static void reportList(HttpServletResponse response, String[] header, String[] properties, String fileName, List<?> sourceList) throws Exception {
        if (header == null || properties == null || sourceList == null || header.length <= 0 || properties.length <= 0 || sourceList.size() <= 0)
            return;
        if (StringUtils.isBlank(fileName)) {
            fileName = "1.csv";
        }
        response.setContentType("application/csv");
        response.setCharacterEncoding("GBK");
        response.setHeader("Content-FileName", URLEncoder.encode(fileName, "UTF-8"));
        response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
        ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(), CsvPreference.STANDARD_PREFERENCE);
        csvWriter.writeHeader(header);
        for (Object obj : sourceList) {
            csvWriter.write(obj, properties);
        }
        csvWriter.close();
    }

    /**
     * 向 response 对象写入一个 CSV 文件
     *
     * @param response   相应对象
     * @param header     需要转换的信息的中文列名集合
     * @param properties 需要转换信息的字段列名集合
     * @param fileName   需要转换为的文件名称
     * @param sourceList csv 转换文件的源数据
     * @param processors processors 对应关系指定 String 类型不需要进行操作，其他的在该类中有对应的属性对象
     * @throws Exception 转换过程 中发生了异常
     */
    public static void reportListCsv(HttpServletResponse response, String[] header, String[] properties, String fileName, List<?> sourceList, CellProcessor[] processors) throws Exception {
        if (header == null || properties == null || sourceList == null || header.length <= 0 || properties.length <= 0 || sourceList.size() <= 0)
            return;
        if (StringUtils.isBlank(fileName)) {
            fileName = "1.csv";
        }
        response.setContentType("application/csv");
        response.setCharacterEncoding("GBK");
        response.setHeader("Content-FileName", URLEncoder.encode(fileName, "UTF-8"));
        response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
        ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(), CsvPreference.STANDARD_PREFERENCE);
        csvWriter.writeHeader(header);
        for (Object obj : sourceList) {
            csvWriter.write(obj, properties, processors);
        }
        csvWriter.close();
    }
}
